package emulator.hardware.io.peripherals;

public class VicTapeState {
	private VicTapeContents contents;
	private StateBase state;

	public VicTapeState()
	{
		contents = new VicTapeContents();
		state = new IdleState();
	}

	public VicTapeTrack getCurrentTrack() {
		return contents.getCurrentTrack();
	}


	public void addTrack(VicTapeTrack track) {
		contents.addTrack(track);
	}
	
	public VicTapeContents getContents() {
		return contents;
	}
	
	synchronized public void handlePlayEvent() { state = state.handlePlayEvent(); }
	synchronized public void handleRecordEvent() { state = state.handleRecordEvent(); }
	synchronized public void handleStopEvent() { state = state.handleStopEvent(); }

	synchronized public boolean performPreReadEvent(boolean signal) { return state.performPreReadEvent(signal); }
	synchronized public boolean performPostReadEvent(boolean signal) { return state.performPostReadEvent(signal); }
	synchronized public boolean performPreWriteEvent(boolean signal) { return state.performPreWriteEvent(signal); }
	synchronized public boolean performPostWriteEvent(boolean signal) { return state.performPostWriteEvent(signal); }

	abstract class StateBase
	{
		StateBase handleRecordEvent() { return this; }
		StateBase handlePlayEvent() { return this; }
		StateBase handleStopEvent() { return this; }
		
		boolean performPreReadEvent(boolean signal) { return signal; }
		boolean performPostReadEvent(boolean signal) { return signal; }
		boolean performPreWriteEvent(boolean signal) { return signal; }
		boolean performPostWriteEvent(boolean signal) { return signal; }
	}
	
	class IdleState extends StateBase
	{
		@Override
		public StateBase handlePlayEvent() {
			return new PlayState(getCurrentTrack());
		}

		@Override
		public StateBase handleRecordEvent() {
			return new RecordState();
		}
	}
	
	class PlayState extends StateBase
	{
		VicTapeTrack track = null;
		long counter = 0;
		
		public PlayState(VicTapeTrack track)
		{
			this.track = track;
		}

		@Override
		public StateBase handleStopEvent() {
			return new IdleState();
		}

		@Override
		public boolean performPreReadEvent(boolean signal) {
			counter++;
			return track.playSignal(counter);
		}

		@Override
		public boolean performPostReadEvent(boolean signal) {
			return signal;
		}
	}
	
	class RecordState extends StateBase
	{
		VicTapeTrack track = new VicTapeTrack();
		boolean last_value = false;
		long counter = 0;
		
		@Override
		public StateBase handleStopEvent() {
			addTrack(track);
			return new IdleState();
		}

		@Override
		public boolean performPreWriteEvent(boolean signal) {
			counter++;
			return signal;
		}

		@Override
		public boolean performPostWriteEvent(boolean signal) {
			if (signal != last_value)
			{
				track.recordSignal(counter, signal);
				last_value = signal;
			}
			return signal;
		}
	}
}
